home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 1 (Walnut Creek)
/
Aminet - June 1993 [Walnut Creek].iso
/
usenet
/
sources
/
volume90
/
devices
/
env2manx.0
/
funcs.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-01-29
|
16KB
|
779 lines
/*
* FILE
* funcs.c
*
* DESCRIPTION
* All the functions for actually read and write the MANX
* environment variables.
*
* AUHOR
* Anders `ALi' Lindgren
* Marlarblick 8
* S-161 51 Bromma
* Sweden
*
* STATUS
* This file is in the Public Domain.
*
* CODE HISTORY
* 26-Sep-89 (10:51) Created this file.
* 27-Sep-89 (18:56) Read works ok.
* (19:27) ReAlloc written.
* (12:00) Both Read and Write works ok.
* 28-Sep-89 (14:00) Locks implemented.
*
* 1-Oct-89 No hacking. I was employed by Commodore,
* ... Sweden at the Alvsjo copmuter fair.
* 6-Oct-89
* 6-Oct-89 (Gee, today I bougth a 2000 :-) )
*
* 6-Oct-89 (23:30) Implemented Directory functions. Some
* people wanted it badly.
* 8-Oct-89 (12:00) Directory functions works ok.
*
* ... (I got my hands on MicroGNUEmacs 3. It`s GREAT!)
*
* 17-Oct-89 I threw out the old directory functions, becauce
* they didn`t function the way I liked.
*
* 20-Jan-90 I`m sorry, but I have been up to my neck into
* other things so I haven`t been able to work
* on the project. Well, now it`s released, enjoy!
*
* DISCUSSION
* Change __builtin_memcpy to CopyMem???
*/
#include "funcs.h"
/*
* FUNCTION
* action_input
*
* DESCRIPTION
* Read an MANX variable. This function copies the variable
* value to a temporary buffer.
*
* The valuebuf structure conatisn the following fields:
* vb_buf - Pointer to the temporary buffer.
* vb_pos - Index, pointing to the next char to be read.
* vb_end - Size of the Buffer.
*
* When vb_pos and vb_end is equal, all data was been read.
*/
void
action_input (register struct DosPacket * pkt, struct MsgPort * port)
{
register struct FileHandle * fh;
register struct valuebuf * vb;
register char * var;
register int len;
char name[NAMESIZE];
char * varname;
pkt->dp_Res1 = DOS_FALSE;
fh = (struct FileHandle *)BTOC(pkt->dp_Arg1);
BtoCStr(name, pkt->dp_Arg3, NAMESIZE-1);
varname = BaseName ( name );
if ( * varname ) {
Forbid();
if (var = mygetenv(varname)) {
if (vb = (struct valuebuf *) AllocMem( sizeof(struct valuebuf),
MEMF_PUBLIC | MEMF_CLEAR ) ) {
fh->fh_Type = port;
fh->fh_Arg1 = (long) vb;
len = __builtin_strlen(var);
if (vb->vb_buf = AllocMem(len, MEMF_PUBLIC | MEMF_CLEAR)) {
vb->vb_end = len;
vb->vb_pos = 0;
__builtin_memcpy(vb->vb_buf, var, len);
vb->vb_flags = ENVF_READ;
pkt->dp_Res1 = DOS_TRUE;
}
else {
pkt->dp_Res2 = ERROR_NO_FREE_STORE;
FreeMem((char *)vb, sizeof(struct valuebuf));
}
}
else {
pkt->dp_Res2 = ERROR_NO_FREE_STORE;
}
}
else {
pkt->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
}
Permit();
}
else {
pkt->dp_Res2 = ERROR_BAD_STREAM_NAME;
}
return;
}
/*
* FUNCTION
* action_read
*
* DESCRIPTION
* Writes the buffer to the fh.
*/
void
action_read (register struct DosPacket * pkt)
{
register struct valuebuf * vb;
register int num;
vb = (struct valuebuf *)pkt->dp_Arg1;
if (vb->vb_flags & ENVF_READ) {
/* Already read all? */
if (vb->vb_pos == vb->vb_end) {
pkt->dp_Res1 = 0;
}
else {
/* Get the smallest, buffer or remaining chars */
if ( (vb->vb_end - vb->vb_pos) <= pkt->dp_Arg3 ) {
num = vb->vb_end - vb->vb_pos;
}
else {
num = pkt->dp_Arg3;
}
__builtin_memcpy( (void *)pkt->dp_Arg2,
(void *)(vb->vb_buf + vb->vb_pos), num );
vb->vb_pos += num;
pkt->dp_Res1 = num;
}
}
else {
pkt->dp_Res1 = 0;
pkt->dp_Res2 = ERROR_OBJECT_WRONG_TYPE;
}
return;
}
/*
* FUNCTION
* action_output
*
* DESCRIPTION
* Open the env: for writing a variable.
* This function allocates memory for the namestring.
* It doesn`t allocate memory for the buffer, because if the
* vb_buf is zero (ie. no write has been made) the Setenv
* function removes the variable.
*/
void
action_output (register struct DosPacket * pkt, struct MsgPort * port)
{
register struct valuebuf * vb;
register char * varname;
register int namelen;
struct FileHandle * fh;
char name[NAMESIZE];
pkt->dp_Res1 = DOS_FALSE;
if (vb = (struct valuebuf *) AllocMem( sizeof(struct valuebuf),
MEMF_PUBLIC | MEMF_CLEAR ) ) {
fh = (struct FileHandle *)BTOC(pkt->dp_Arg1);
BtoCStr(name, pkt->dp_Arg3, NAMESIZE-1);
varname = BaseName( name );
if ( * varname ) {
namelen = __builtin_strlen(varname) + 1;
if (vb->vb_name = DosAllocMem(namelen)) {
__builtin_memcpy(vb->vb_name, varname, namelen);
fh->fh_Type = port;
fh->fh_Arg1 = (long) vb;
vb->vb_flags = ENVF_WRITE;
pkt->dp_Res1 = DOS_TRUE;
return; /* Correct exit */
}
/* Error hancdling code */
else {
pkt->dp_Res2 = ERROR_NO_FREE_STORE;
}
}
else {
pkt->dp_Res2 = ERROR_BAD_STREAM_NAME;
}
FreeMem((char *)vb, sizeof(struct valuebuf));
}
else {
pkt->dp_Res2 = ERROR_NO_FREE_STORE;
}
return; /* Error Exit! */
}
/*
* FUNCTION
* action_write
*
* DESCRIPTON
* Called when a client writes the contents of a environment
* variable.
* The data is stored at at buffer. If the buffer is smaler
* than the data, the buffer is expanded.
* BUFSIZE is the amount of extra memory which shall be
* allocated at a ReAlloc call.
* (If BUFSIZE is zero, a ReAlloc call will be made at
* every write.)
*
* NOTE
* No errorchecking is made on the ReAlloc function, yet....
*/
void
action_write (register struct DosPacket * pkt)
{
register struct valuebuf * vb;
register char * newbuf;
vb = (struct valuebuf *)pkt->dp_Arg1;
if (vb->vb_flags & ENVF_WRITE) {
if (vb->vb_pos + pkt->dp_Arg3 + 1 >= vb->vb_end) {
newbuf = ReAlloc(vb->vb_buf, vb->vb_end,
vb->vb_end + pkt->dp_Arg3 + BUFSTEP, MEMF_CLEAR);
if (newbuf == NULL) {
FreeMem (vb->vb_buf, vb->vb_end);
DosFreeMem (vb->vb_name);
FreeMem ((char *)vb, sizeof(struct valuebuf));
pkt->dp_Res1 = 0;
pkt->dp_Res2 = ERROR_NO_FREE_STORE;
return;
}
vb->vb_buf = newbuf;
vb->vb_end += pkt->dp_Arg3 + BUFSTEP;
}
__builtin_memcpy(vb->vb_buf + vb->vb_pos, (void *)pkt->dp_Arg2,
pkt->dp_Arg3);
vb->vb_pos += pkt->dp_Arg3;
pkt->dp_Res1 = pkt->dp_Arg3;
}
else {
pkt->dp_Res1 = 0;
pkt->dp_Res2 = ERROR_OBJECT_WRONG_TYPE;
}
return;
}
/*
* FUNCTION
* action_end
*
* DESCRIPTION
* This function is executed when someone Close()`s the filehandler.
*
* On read, it simply frees the memory. On Write, the actual
* writing takes place here.
*/
void
action_end (register struct DosPacket * pkt)
{
register struct valuebuf * vb;
pkt->dp_Res1 = DOS_FALSE;
if (vb = (struct valuebuf *)pkt->dp_Arg1) {
if (vb->vb_flags & ENVF_READ) {
if (vb->vb_buf && vb->vb_end) {
FreeMem( (char *)vb->vb_buf, vb->vb_end);
FreeMem( (char *)vb, sizeof(struct valuebuf) );
}
pkt->dp_Res1 = DOS_TRUE;
}
else if (vb->vb_flags & ENVF_WRITE) {
if (vb->vb_name) {
Setenv(vb->vb_name, vb->vb_buf);
DosFreeMem(vb->vb_name);
}
if (vb->vb_buf) {
FreeMem(vb->vb_buf, vb->vb_end);
}
FreeMem((char *)vb, sizeof(struct valuebuf));
pkt->dp_Res1 = DOS_TRUE;
}
else { /* Error */
pkt->dp_Res2 = ERROR_OBJECT_WRONG_TYPE;
}
}
else {
pkt->dp_Res2 = ERROR_OBJECT_WRONG_TYPE;
}
return;
}
/*
* FUNCTION
* action_lock
*
* DESCRIPTION
* Lock the env: device, or a `file'. If a file is locked, the filename
* is copied to a aread pointed to by lock->fl_Name.
*
* ARGUMENTS
* Arg1 : Lock
* Arg2 : Name
* Arg3 : Mode
*/
void
action_lock (register struct DosPacket * pkt,
struct MsgPort * port,
struct DosList * node)
{
register struct myFileLock * lock;
char name[NAMESIZE];
char * namebase;
pkt->dp_Res1 = NULL;
if (lock = (struct myFileLock *)AllocMem(sizeof(struct myFileLock),
MEMF_PUBLIC | MEMF_CLEAR)) {
pkt->dp_Res1 = CTOB(lock);
lock->fl_Access = pkt->dp_Arg3;
lock->fl_Task = port;
lock->fl_Volume = CTOB(node);
BtoCStr(name, pkt->dp_Arg2, NAMESIZE-1);
if (* (namebase = BaseName( name ))) {
if ( (lock->fl_Name = getenvname( namebase )) == NULL ) {
FreeMem ((char *)lock, sizeof(struct myFileLock));
pkt->dp_Res1 = NULL;
pkt->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
}
}
}
else {
pkt->dp_Res2 = ERROR_NO_FREE_STORE;
}
return;
}
/*
* FUNCTION
* action_copy_lock
*
* DESCRIPTION
* Implement the DupLock function.
*/
void
action_copy_lock (register struct DosPacket * pkt)
{
register struct myFileLock * newlock;
register struct myFileLock * oldlock;
register int namelen;
pkt->dp_Res1 = NULL;
if (oldlock = (struct nyFileLock *)BTOC(pkt->dp_Arg1)) {
if (newlock = (struct myFileLock *)AllocMem(sizeof(struct myFileLock),
MEMF_PUBLIC | MEMF_CLEAR)) {
pkt->dp_Res1 = CTOB(newlock);
newlock->fl_Access = oldlock->fl_Access;
newlock->fl_Task = oldlock->fl_Task;
newlock->fl_Volume = oldlock->fl_Volume;
if (oldlock->fl_Name) {
namelen = __builtin_strlen(oldlock->fl_Name);
if (newlock->fl_Name = DosAllocMem( namelen + 1 )) {
__builtin_memcpy (newlock->fl_Name, oldlock->fl_Name, namelen );
}
else {
pkt->dp_Res1 = NULL;
pkt->dp_Res2 = ERROR_NO_FREE_STORE;
FreeMem ((char *) newlock, sizeof(struct myFileLock));
}
}
}
else {
pkt->dp_Res2 = ERROR_NO_FREE_STORE;
}
}
return;
}
/*
* FUNCTION
* action_freelock
*
* DESCRIPTION
* Frees the lock.
*/
void
action_freelock(register struct DosPacket * pkt)
{
register struct myFileLock * lock;
if (lock = BTOC(pkt->dp_Arg1)) {
if (lock->fl_Name) {
DosFreeMem((char *) lock->fl_Name);
}
FreeMem((char *)lock, sizeof(struct myFileLock));
}
pkt->dp_Res1 = DOS_TRUE;
return;
}
/*
* FUNCTION
* action_delete
*
* DESCRIPTION
* Delete a MANX variable.
*/
void
action_delete(register struct DosPacket * pkt)
{
char name[NAMESIZE];
char * varname;
BtoCStr(name, pkt->dp_Arg2, NAMESIZE-1);
varname = BaseName( name );
if (* varname) {
if (Setenv(varname, NULL)) {
pkt->dp_Res1 = DOS_TRUE;
}
else {
/* As close at is can be. */
pkt->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
}
}
else {
pkt->dp_Res2 = ERROR_BAD_STREAM_NAME;
}
return;
}
/*
* FUNCTION
* action_examine_object
*
* DESCRIPTION
* This function returns information about either ENV: itself
* os a single varable. It fills in the FileInfoBlock with
* appropriate values.
*/
void
action_examine_object(register struct DosPacket * pkt)
{
register struct myFileLock * lock;
register struct FileInfoBlock * fib;
if (lock = (struct myFileLock *) BTOC(pkt->dp_Arg1)) {
if (fib = (struct FileInfoBlock *)BTOC(pkt->dp_Arg2)) {
if (lock->fl_Name == NULL) {
fib->fib_DiskKey = FIRST_KEY;
fib->fib_DirEntryType = 2; /* Directory */
fib->fib_EntryType = 2;
fib->fib_Size = 0;
fib->fib_NumBlocks = 0;
CtoBStr( "ENV", CTOB(fib->fib_FileName), 4);
}
else {
fib->fib_DiskKey = FIRST_KEY;
fib->fib_DirEntryType = -3;
fib->fib_EntryType = -3;
Forbid();
fib->fib_Size =
__builtin_strlen(mygetenv(lock->fl_Name));
Permit();
fib->fib_NumBlocks = 1;
CtoBStr ( lock->fl_Name, CTOB(fib->fib_FileName), 30);
}
fib->fib_Protection = 0x00; /* ----rwed */
fib->fib_Comment[0] = 0;
/* DateStamp( (long *) & fib->fib_Date ); /* Edit later! */
pkt->dp_Res1 = DOS_TRUE;
}
else { /* No fib */
pkt->dp_Res2 = ERROR_OBJECT_WRONG_TYPE;
}
}
else { /* No lock */
pkt->dp_Res2 = ERROR_INVALID_LOCK;
}
return;
}
/*
* FUNCTION
* action_examine_next
*
* DESCTIPTION
* This function:
* - handles the `examine next' packet.
* - is called as part of `examine object' funcetion.
*
* It fills in the `FileInfoBlock' with appropriate values.
*/
void
action_examine_next (register struct DosPacket * pkt)
{
register struct myFileLock * lock;
register struct FileInfoBlock * fib;
register char * newname;
register LONG namelen;
if (lock = (struct myFileLock *) BTOC(pkt->dp_Arg1)) {
if (fib = (struct FileInfoBlock *)BTOC(pkt->dp_Arg2)) {
Forbid();
if (newname = getnextenv(fib, pkt) ) {
for (namelen = 0; newname[namelen] != '='; namelen++)
;
fib->fib_DiskKey += 1;
fib->fib_DirEntryType = -3;
fib->fib_Protection = 0x00; /* ----rwed */
fib->fib_EntryType = -3;
fib->fib_Size =
__builtin_strlen(newname) - namelen - 1;
fib->fib_NumBlocks = 1;
/* DateStamp( (long *) & fib->fib_Date ); /* Edit later! */
fib->fib_Comment[0] = 0;
__builtin_memcpy( fib->fib_FileName + 1, newname, namelen);
fib->fib_FileName[0] = namelen;
pkt->dp_Res1 = DOS_TRUE;
}
Permit();
}
else {
pkt->dp_Res2 = ERROR_OBJECT_WRONG_TYPE;
}
}
else {
pkt->dp_Res2 = ERROR_INVALID_LOCK;
}
return;
}
/*
* FUNCTION
* mygetenv
*
* DESCRIPTION
* Get a MANX environment variable.
* I can`t use the Arp function `getenv', because it will call
* ENV: if the variable doesn`t exist in the MANX area, resulting
* in a loop loop loop loop loop.....
*
* The EnvSpace is builtup by strings in the form:
* name=value
* They are separated by one \0 and they are ended by two.
*
* NOTE
* The task MUST be Forbid()`ed before this function is called!
*/
static char *
mygetenv(register char * name)
{
register char * p;
register int len;
if ( p = ((struct EnvBase*)ArpBase->EnvBase)->EnvSpace ) {
len = __builtin_strlen(name);
while (*p) {
if (Strncmp(p, name, len) == 0) {
if ( p[len] == '=' ) {
return (& p[len+1]);
}
}
p += __builtin_strlen(p) + 1;
}
}
return(NULL);
}
/*
* FUNCTION
* getnextenv
*
* DESCRIPTION
* Get the next environment variable. If an error accured the correct
* errorcode is placed in pkt->dp_Res2 and a NULL is returned.
*
* NOTE
* This function MUST be called in Forbid()`ed state.
*/
static char *
getnextenv (register struct FileInfoBlock * fib, register struct DosPacket * pkt)
{
register char * p;
register int len;
if ( p = ((struct EnvBase*)ArpBase->EnvBase)->EnvSpace ) {
if (fib->fib_DirEntryType > 0) {
if (*p) {
return (p);
}
else {
pkt->dp_Res2 = ERROR_NO_MORE_ENTRIES;
return (NULL);
}
}
while (*p) {
len = __builtin_strlen(p);
if ( (Strncmp(p, fib->fib_FileName + 1,
* fib->fib_FileName) == 0)
&& (p[* fib->fib_FileName] == '=') ) {
if ( * (p + len + 1) ) {
return (p + len + 1);
}
else {
pkt->dp_Res2 = ERROR_NO_MORE_ENTRIES;
return (NULL);
}
}
p += len + 1;
}
pkt->dp_Res2 = ERROR_OBJECT_NOT_FOUND; /* Correct??? */
}
return (NULL); /* No environment at all, or entry not found */
}
/*
* FUNCTION
* getenvname
*
* DESCRIPTION
* Get the name of an environment variable.
*
* NOTE
* This function MUST be called in Forbid()`ed state!
*/
static char *
getenvname( register char * orgname )
{
register char * p;
register int len;
register char * newname;
register int namelen;
if ( p = ((struct EnvBase*)ArpBase->EnvBase)->EnvSpace ) {
namelen = __builtin_strlen( orgname );
while (*p) {
len = __builtin_strlen(p);
if ( (Strncmp(p, orgname, namelen) == 0) &&
(p[namelen] == '=') ) {
newname = DosAllocMem (namelen+1);
__builtin_memcpy( newname, p, namelen );
return ( newname );
}
p += len + 1;
}
}
return (NULL);
}
/*
* FUNCTION
* ReAlloc
*
* DESCRIPTION
* Alloctes a biger memory area and copies the contens of
* the original block. It then releases the original
* block.
*
* RETURNS
* A pointer to the new memory block. Or a NULL is
* AllocMem failed, in which case the original
* memory block is NOT released.
*/
static void *
ReAlloc ( void * oldbuf, long oldsize, long newsize, long flags )
{
void * newbuf;
if (newbuf = AllocMem(newsize, flags)) {
if ((oldbuf != NULL) && (oldsize != 0L)) {
__builtin_memcpy( newbuf, oldbuf, MAX(oldsize, newsize) );
FreeMem( oldbuf, oldsize );
}
}
return (newbuf);
}